#pragma once

#include "platform/platform.h"
#include <functional>


struct event;
struct event_base;


namespace EZTcp{

class EZLoop;

class EZSocketFD
{
public:
	enum EventType {
		kNone = 0x00,
		kReadable = 0x02,
		kWritable = 0x04,
	};
	typedef std::function<void()> EventCallback;
	typedef std::function<void()> ReadEventCallback;

public:
	EZSocketFD(EZLoop* loop, ez_socket_t fd,
		bool watch_read_event, bool watch_write_event);
	~EZSocketFD();

	void destroy();

	// Attach this FdChannel to EventLoop
	void attach_to_loop();

	bool attached() const {
		return attached_;
	}

public:
	bool is_readable() const {
		return (events_ & kReadable) != 0;
	}
	bool is_writable() const {
		return (events_ & kWritable) != 0;
	}
	bool is_none_event() const {
		return events_ == kNone;
	}

	void enable_read_event();
	void enable_write_event();
	void disable_read_event();
	void disable_write_event();
	void disable_all_event();

public:
	ez_socket_t fd() const {
		return fd_;
	}
	std::string events_to_string() const;

public:
	void set_read_callback(const ReadEventCallback& cb) {
		read_fn_ = cb;
	}

	void set_write_callback(const EventCallback& cb) {
		write_fn_ = cb;
	}

private:
	void HandleEvent(ez_socket_t fd, short which);
	static void HandleEvent(ez_socket_t fd, short which, void* v);

	void _update();
	void _detach_from_loop();
private:
	ReadEventCallback read_fn_;
	EventCallback write_fn_;

	EZLoop* loop_;
	bool attached_; // A flag indicate whether this FdChannel has been attached to loop_

	struct event* event_;
	int events_; // the bitwise OR of zero or more of the EventType flags

	ez_socket_t fd_;
};


}


